package com.zhj.rabbitmq.demo2;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @program: rabbimmq-demo
 * @description: 使用交换机 Direct（Direct类型交换机） 发送消息
 * @author: zhengjibin
 * @create: 2020-11-16 17:02
 * @Version 1.0
 **/
public class ExchangeDirectSendMessage {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        //配置rabbitmq的链接信息
        factory.setHost("122.112.198.94");
        factory.setPort(5672);
        factory.setUsername("admin");
        factory.setPassword("admin");
        Connection connection = null;// 定义rabbitmq的网络连接 ，一个连接
        Channel channel = null;//定义一个链接中的通道
        connection = factory.newConnection();//通过工厂获得连接
        channel = connection.createChannel();//通过连接获得通道

         /*
            生成一个队列，queueDeclare()方法有很多的重载方法，具体使用，参考源码
             channel.queueDeclare();//方法 5个参数说明
            参数1：队列名称自定义
            参数2：是否为持久化的队列
            参数3：是否排外是排外的话就只能一个客户端监听
            参数4：是否是自动删除设置了true表示自动删除队列没有数据没有客户端连接时删除
            参数5:队列的一些属性设置一般设置为null

            注意：声明队列时，如果rabbitmq中 队列名称有就直接使用，没有就创建队列

            //channel.queueDeclare(queueName,true,false,false,null); // 这行代码可以不存在
            如果这个队列名称已经在rabbitmq中有就不用 这一句了
         */String queueName = "demo2_queue";
        channel.queueDeclare(queueName,true,false,false,null);
        //生成消息队列,如果 rabbitmq中已经有queueName 队列了，那么可以不用这一句代码。也可以在管控台中创建
                                                                                //生成消息队列 。可以在消费端创建队列，也能在生产端创建队列。
        /*
            声明一个交换机
            参数1：交换机名称
            参数2：参数类型，direct或fanout，或topic，或headers
            参数3：是否持久化交换机
            注意：声明交换机时，如果这个交换机名称已经存在，就直接使用，否则才创建交换机
                声明交换机的代码可以不写，但是必须保证rabbitmq中已经有这个交换机了
         */
        String exchangeName = "demo2_exchange";
        channel.exchangeDeclare(exchangeName,"direct",true);
        /*
            将队列绑定到交换机 ，并指定队列和交换机绑定的binding
            参数1：队列名称
            参数2：交换机名称
            参数3：消息的routingkey（就是bindingkey）。就是队列绑定到bings 上的bindingkey
            注意：在交换机和消息队列绑定时，必须确认消息队列和交换机已经成功声明
         */
        String routingkey = "demoRoutingKey";
        channel.queueBind(queueName,exchangeName,routingkey);

        String message = "交换机消息333";
        /*
            发送消息
            参数1：交换机名称，空字符串表示不使用交换机
            参数2：表示队列名或routingkey，当指定了交换机名称后，这个值就是routingkey。没有指定交换机就表示队列名称
            参数3：参数属性，一般为空
            参数4：消息内容的字节数组
            注意：发送前，必须确认交换机和消息队列已经成功创建，并且确认交换机已经绑定到消息队列
         */
        /*
            注意：此方法的 routingkey 是指定消息的 routingkey 。消息中的routingkey 必须和 交换机和消息队列绑定是binding规则中的bindingkey一直
         */
        channel.basicPublish(exchangeName,routingkey,null,message.getBytes("UTF-8"));

        System.out.println("消息发送成功");

        channel.close();
        connection.close();
    }
}
